package com.choudou5.solr.web.handler;

import com.choudou5.solr.annotation.ReqMapping;
import com.choudou5.solr.bean.common.ReqMappingBean;
import com.choudou5.solr.framework.constants.ErrorResp;
import com.choudou5.solr.framework.util.PageJumpUtil;
import com.choudou5.solr.framework.util.UserUtil;
import com.choudou5.solr.service.ServiceHelper;
import com.choudou5.solr.service.SysUserService;
import com.choudou5.solr.util.BeanMapper;
import com.choudou5.solr.util.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @Name：说明
 * @Author：choudou5
 * @Date：2018-07-14
 */
public abstract class BaseHandler {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    protected final static SysUserService sysUserService = ServiceHelper.singleton(SysUserService.class);

    /**
     * 执行器
     * @param bizMethod
     * @param req
     * @param resp
     */
    public abstract void execute(String bizMethod, HttpServletRequest req, HttpServletResponse resp);

    protected Map<String, Object> buildMap(HttpServletRequest request){
        if (request.getContentLength() > 0) {
            Map<String, Object> param = new HashMap<>();
            Enumeration en = request.getParameterNames();
            if(en != null){
                String name = null, val = null;
                while (en.hasMoreElements()){
                    name = en.nextElement().toString();
                    val = request.getParameter(name);
                    if(val != null){
                        if(name.contains("Time")){
                            param.put(name, DateUtil.parse(val));
                        }else{
                            param.put(name, val);
                        }
                    }
                }

            }
            return param;
        }
        return null;
    }

    protected <T> T buildBean(HttpServletRequest request, Class<T> clssz){
        if (request.getContentLength() > 0) {
            Map<String, Object> param = new HashMap<>();
            Field[] fields = clssz.getDeclaredFields();
            String val = null;
            for (Field field : fields) {
                val = request.getParameter(field.getName());
                if(val != null){
                    if(field.getName().contains("Time")){
                        param.put(field.getName(), DateUtil.parse(val));
                    }else{
                        param.put(field.getName(), val);
                    }
                }

            }
            return BeanMapper.map(param, clssz);
//            byte[] body = new byte[request.getContentLength()];
//            try {
//                IOUtils.readFully(request.getInputStream(), body);
//                String requestBody = new String(body, "utf-8");
//                logger.info("request body = {}", requestBody);
//                return JsonUtil.toJavaObj(requestBody, clssz);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
        }
        return null;
    }


    protected boolean validParam(HttpServletRequest req, HttpServletResponse resp, Object paramVal, String paramName){
        return validParam(req, resp, new Object[]{paramVal}, new String[]{paramName});
    }

    protected boolean validParam(HttpServletRequest req, HttpServletResponse resp, Object[] paramVals, String[] paramNames){
        if(paramVals.length != paramNames.length){
            PageJumpUtil.errorOut(ErrorResp.Error, req, resp);
            return false;
        }
        boolean valid = true;
        String message = null;
        for (int i = 0; i < paramNames.length; i++) {
            if(paramVals[i] == null || paramVals[i].toString().length() == 0){
                message = paramNames[i]+" 参数无效";
                valid = false;
            }
        }
        if(!valid){
            PageJumpUtil.errorOut(ErrorResp.INVALID_PARAM, message, req, resp);
        }
        return valid;
    }

    protected boolean validParam(HttpServletRequest req, HttpServletResponse resp, Map<String, Object> paramMap, String[] paramNames){
        boolean valid = true;
        StringBuilder message = new StringBuilder();
        Object paramVal = null;
        for (String paramName : paramNames) {
            paramVal = paramMap.get(paramName);
            if(paramVal == null || paramVal.toString().length() == 0){
                if(message.length() > 0){
                    message.append(", ");
                }
                message.append("参数"+paramName+"无效");
                valid = false;
            }
        }
        if(!valid){
            PageJumpUtil.errorOut(ErrorResp.INVALID_PARAM, message.toString(), req, resp);
        }
        return valid;
    }


    protected boolean isAdmin(HttpServletRequest req, HttpServletResponse resp){
        if(!UserUtil.isAdmin()) {
            PageJumpUtil.errorOut(ErrorResp.Forbidden, req, resp);
            return false;
        }
        return true;
    }

    protected boolean isSuperAdmin(HttpServletRequest req, HttpServletResponse resp){
        if(!UserUtil.isSuperAdmin()) {
            PageJumpUtil.errorOut(ErrorResp.Forbidden, req, resp);
            return false;
        }
        return true;
    }


    private boolean checkReqType(HttpServletRequest request, String defMethodType){
        String method = request.getMethod();
        return method.equalsIgnoreCase(defMethodType);
    }

    private static final Map<String, ReqMappingBean> cache = new HashMap<>();

    protected void cacheReqMapping() {
        String className = getClass().getSimpleName();
        Method[] methods = getClass().getDeclaredMethods();
        String cacheKey = null;
        for (Method method : methods) {
            ReqMapping ann = method.getAnnotation(ReqMapping.class);
            if(ann != null){
                cacheKey = className+"_"+method.getName();
                System.out.println(cacheKey);
                cache.put(cacheKey, new ReqMappingBean(ann.method().name(), ann.desc()));
            }
        }
    }

    public static boolean checkReqMapping(String module, String api, String method) {
        String cacheKey = module+"_"+api;
        ReqMappingBean reqMapping = cache.get(cacheKey);
        if(reqMapping != null){
            return method.equalsIgnoreCase(reqMapping.getMethod());
        }
        return true;
    }


    {
        cacheReqMapping();
    }

}
